package cn.xdf.docscan.view

import android.animation.ValueAnimator
import android.content.Context
import android.graphics.*
import android.util.AttributeSet
import android.util.Log
import android.view.View
import android.view.animation.LinearInterpolator
import java.util.*

/**
 * 四边形标记视图
 * 1:1复刻原项目的QuadrilateralView
 */
class QuadrilateralView @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0
) : View(context, attrs, defStyleAttr) {

    companion object {
        private const val TAG = "QuadrilateralView"
    }

    // 完全按照原项目的成员变量
    private val detectionPaths = mutableListOf<Path>()      // 检测路径列表
    private val boundaryPaths = mutableListOf<Path>()       // 边界路径列表
    private val cornerPoints = mutableListOf<PointF>()      // 角点列表
    private val centers = mutableListOf<PointF>()           // 中心点
    private val otherPaths = mutableListOf<Path>()          // 其他路径列表

    // 绘制相关（固定颜色与固定透明度，避免动画引起的明暗变化）
    private val strokePaint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
        style = Paint.Style.STROKE
        strokeWidth = resources.displayMetrics.density * 3.5f
        strokeJoin = Paint.Join.ROUND
        color = Color.BLUE
        alpha = 80 // 20% 透明度
    }
    private val fillPaint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
        style = Paint.Style.FILL
        color = Color.BLUE
        alpha = 80 // 20% 透明度
    }
    private val boundaryPaint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
        style = Paint.Style.STROKE
        strokeWidth = resources.displayMetrics.density * 3f
        strokeJoin = Paint.Join.ROUND
        color = Color.WHITE
        alpha = 80 // 20% 透明度
    }
    private val cornerPaint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
        style = Paint.Style.FILL
        color = Color.BLUE
        alpha = 80 // 20% 透明度
    }

    private val cornerRadius = resources.displayMetrics.density * 3.5f

    // 动画相关：在角点变化较大时做短动画过渡（仅位置插值，不改透明度）
    private var animator: ValueAnimator? = null
    private var animStartCorners: List<List<PointF>> = emptyList()
    private var animTargetCorners: List<List<PointF>> = emptyList()
    private var currentCorners: MutableList<List<PointF>> = mutableListOf()
    private val moveThresholdPx = 12f
    private val animDurationMs = 180L

    init {
        // 初始不启动动画，待 onSizeChanged 创建渐变后启动
    }

    override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
        super.onSizeChanged(w, h, oldw, oldh)
        // 不做渐变初始化，保持固定颜色
        animator?.cancel()
        animator = null
    }

    override fun onDraw(canvas: Canvas) {
        super.onDraw(canvas)

        // 1. 固定颜色描边 + 固定透明度填充（仅绘制一次）
        val path = detectionPaths.getOrNull(0) ?: return
        canvas.drawPath(path, strokePaint)
        canvas.drawPath(path, fillPaint)

        // 2. 绘制边界路径
        // 不再单独绘制边界，避免重复画出第二个框

        // 3. 绘制角点
        for (point in cornerPoints) {
            canvas.drawCircle(point.x, point.y, cornerRadius, cornerPaint)
        }
        // 3.5 绘制中心点
        for (c in centers) {
            canvas.drawCircle(c.x, c.y, cornerRadius * 0.8f, cornerPaint)
        }

//        // 4. 绘制其他路径
//        for (path in otherPaths) {
//            canvas.drawPath(path, strokePaint)
//        }
    }

    /**
     * 更新检测结果
     * 完全按照原项目的逻辑
     */
    fun updateDetection(detections: List<Detection>) {
        val target: List<List<PointF>> =
            detections.map { d -> d.corners.map { PointF(it.x, it.y) } }

        if (currentCorners.isEmpty() || currentCorners.size != target.size) {
            currentCorners = target.map { it.map { p -> PointF(p.x, p.y) } }.toMutableList()
            rebuildPathsFrom(currentCorners)
            invalidate()
            return
        }

        var needAnim = false
        loop@ for (i in target.indices) {
            val from = currentCorners[i]
            val to = target[i]
            val n = minOf(from.size, to.size)
            for (k in 0 until n) {
                val dx = to[k].x - from[k].x
                val dy = to[k].y - from[k].y
                if ((dx * dx + dy * dy) > (moveThresholdPx * moveThresholdPx)) {
                    needAnim = true; break@loop
                }
            }
        }

        if (!needAnim) {
            currentCorners = target.map { it.map { p -> PointF(p.x, p.y) } }.toMutableList()
            rebuildPathsFrom(currentCorners)
            invalidate()
            return
        }

        animStartCorners = currentCorners.map { it.map { p -> PointF(p.x, p.y) } }
        animTargetCorners = target
        animator?.cancel()
        animator = ValueAnimator.ofFloat(0f, 1f).apply {
            duration = animDurationMs
            interpolator = LinearInterpolator()
            addUpdateListener { va ->
                val t = va.animatedValue as Float
                val blended = mutableListOf<List<PointF>>()
                for (i in animTargetCorners.indices) {
                    val from = animStartCorners[i]
                    val to = animTargetCorners[i]
                    val n = minOf(from.size, to.size)
                    val corners = ArrayList<PointF>(n)
                    for (k in 0 until n) {
                        val x = from[k].x + (to[k].x - from[k].x) * t
                        val y = from[k].y + (to[k].y - from[k].y) * t
                        corners.add(PointF(x, y))
                    }
                    blended.add(corners)
                }
                currentCorners = blended
                rebuildPathsFrom(currentCorners)
                invalidate()
            }
            start()
        }
    }

    private fun rebuildPathsFrom(cornerSets: List<List<PointF>>) {
        detectionPaths.clear()
        boundaryPaths.clear()
        cornerPoints.clear()
        centers.clear()
        otherPaths.clear()

        for (corners in cornerSets) {
            if (corners.size < 4) continue
            val path = Path()
            path.moveTo(corners[0].x, corners[0].y)
            for (i in 1 until corners.size) path.lineTo(corners[i].x, corners[i].y)
            path.close()
            detectionPaths.add(path)
            boundaryPaths.add(path)
            cornerPoints.addAll(corners)
            val cx = (corners[0].x + corners[1].x + corners[2].x + corners[3].x) / 4f
            val cy = (corners[0].y + corners[1].y + corners[2].y + corners[3].y) / 4f
            centers.add(PointF(cx, cy))
        }
    }

    /**
     * 清除检测结果
     */
    fun clearDetection() {
        detectionPaths.clear()
        boundaryPaths.clear()
        cornerPoints.clear()
        otherPaths.clear()
        invalidate()
    }

    /**
     * 检测结果数据类
     */
    data class Detection(
        val corners: List<PointF>,
        val confidence: Float
    )

    override fun onDetachedFromWindow() {
        super.onDetachedFromWindow()
        animator?.cancel()
    }
} 